package general.CPA;

import general.ChannelAgent;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Iterator;

public class ArrayCPA extends CPA{

	int n;
	byte[] assignment;
	
	/**
	 * FOR PROTOTYPE ONLY, DO NOT USE THIS CONSTRUCTOR TO MAKE CPA's
	 */
	public ArrayCPA() {
		super();
	}
	
	protected ArrayCPA(int n, int cpaId, int creator) {
		super(cpaId, creator,  0);
		this.n = n;
		assignment = new byte[n];
		for (int i=0; i<n; i++){
			assignment[i] = -1;
		}
		resetSteps();
	}

	protected ArrayCPA(int id, int steps, int creator, byte[] cpa){
		super(id, creator, steps);
		this.n = cpa.length;
		this.assignment = cpa;
	}

	@Override
	public byte getValue(byte i) {
		return assignment[i];
	}

	@Override
	public void insert(byte var, byte value) {
		assignment[var] = value;
	}

	@Override
	public boolean isAssigned(byte i) {
		return assignment[i] != -1;
	}

	@Override
	public Iterator<Integer> iterator() {
		return new MyIterator();
	}

	private class MyIterator implements Iterator<Integer>{
		byte i = 0;
		public MyIterator() {
			while (i<n && !isAssigned(i)){	i++; }
		}

		@Override
		public boolean hasNext() {
			return i<n;
		}

		@Override
		public Integer next() {
			int tmp = i;
			i++;
			while (i<n && !isAssigned(i)){	i++; } 
			return tmp;
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException("remove() unsupported for ArrayCurrentDomain");
		}
	}

	@Override
	public byte[] getBytes() {
		ByteBuffer buf = ByteBuffer.allocate(4+4+4+n);
		buf.putInt(getCpaId());
		buf.putInt(getCreator());
		buf.putInt(getSteps());
		buf.put(assignment);
		return buf.array();
	}
	
	@Override
	public byte getType(){
		return ChannelAgent.SEND_CPA;
	}
	
	@Override
	public int byteSize() {
		return (4+4+4+n);
	}

	@Override
	public void remove(byte i) {
		assignment[i] = -1;
	}

	@Override
	public String toString() {
		String str = "";
		str+=("[");
		for (int i=0; i<n-1; i++){
			str+=(assignment[i] +", ");
		}
		str+=(assignment[n-1]+"] " + getId().toString());
		return str;
	}

	@Override
	public boolean isFull() {
		for (int i=0; i<n; i++){
			if (assignment[i]==-1) return false;
		}
		return true;
	}

	@Override
	public CPA duplicate(int id, byte creator) {
		byte[] assignment2 = Arrays.copyOf(assignment, n);
		return new ArrayCPA(id, 0, creator, assignment2);
	}
	
	@Override
	public CPA createNew(int n, int cpaId, int creator) {
		return new ArrayCPA(n, cpaId, creator);
	}
	@Override
	public CPA createNew(int id, int steps, int creator, byte[] cpa, byte[] order) {
		return new ArrayCPA(id, steps, creator, cpa);
	}
}
